#ifndef SANDBOX_SDK_UTIL_POOL_ALLOCATOR_HPP
#define SANDBOX_SDK_UTIL_POOL_ALLOCATOR_HPP

#include "obstack_allocator.hpp"

namespace sandbox
{
	namespace sdk 
	{
		/**
		 * \brief template <size_t SIZE> class RawPoolAllocator;
		 *        An allocator, which can quickly allocate chunks of 
		 *        size 'SIZE'.
		 * 
		 * RawPoolAllocator is movable, noncopyable allocator
		 * useful to quicky allocate temporary lists. In contrast with 
		 * RawObstackAllocator, RawPoolAllocator reuses recently used
		 * deallocated chunks. However, be aware that this allocator
		 * does not deallocate memory it grabbed into internal pool.
		 */
		template  <size_t CHKSIZE, size_t SIZE, size_t ALIGN> class RawPoolAllocator :
			protected RawObstackAllocator<CHKSIZE, SIZE, ALIGN>
		{
			static_assert(SIZE>sizeof(void*));
		public:
			enum {allocation_unit=detail::sizealign(SIZE,ALIGN)};
			RawPoolAllocator():m_queue(NULL){}
			~RawPoolAllocator()throw(){}
			RawPoolAllocator(RawPoolAllocator&&)=default;
			RawPoolAllocator& operator =(RawPoolAllocator&&)=default;
			void* allocate(size_t nr) {
				if(nr>1)throw std::bad_alloc();
				
				if(m_queue!=NULL){
					void * result=m_queue;
					m_queue=*((void**)m_queue);
				}else{
					return RawObstackAllocator::alloc(1);
				}
			}
			void deallocate(void * ptr,size_t nr) throw() {
				do{
					*((void**)ptr)=m_queue;
					m_queue=ptr;
				}while(ptr+=allocation_unit,--nr);
			}
			size_t max_size()const{return 1;}
		private:
			void * m_queue;
		};

		
	}
}
#endif //SANDBOX_SDK_UTIL_POOL_ALLOCATOR_HPP
